/*
* Nettle Source File.
* Copyright (C) 2013, Nettle (http://nttl.ru/).
*
* This file is part of NettleMath.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-2.1.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* Description:
*
* History:
* Created by Sergey Serb, l-proger@yandex.ru
*/

#ifndef NVector2_h__
#define NVector2_h__

#include "NVectorBase.h"
#include "NVector2.h"
#include "NMathTypes.h"
#include "NMathUtils.h"
#include <type_traits>

namespace NettleMath{
    template<typename T>
    struct NVector2 : NVectorBase<T, 2>{
        T x, y;

        //constructors
        NVector2(){
        }
        NVector2(const NVector2<T>& val)
            :x(val.x), y(val.y){
        }
        NVector2(T val)
            :x(val), y(val){
        }
        NVector2(const T& val_x, const T& val_y)
            :x(val_x), y(val_y){
        }

        //methods
        void set(const T& vx, const T& vy) {
            x = vx;
            y = vy;
        }
        void set(const T& v) {
            x = y = v;
        }
        const NVector2<bool> isEqual3(const NVector2<T>& other){
            return NVector2<bool>(x == other.x, y == other.y);
        }
        T length(){
            return std::sqrt(x*x + y*y);
        }
        T lengthSquared(){
            return x*x + y*y;
        }
        void normalize(){
            T len = length();
			assert(len != 0 && "vec4:normalize division by zero");
            x /= len;
            y /= len;
        }

        //operators
        bool operator == (const NVector2& v){
            return (x == v.x) && (y == v.y);
        }
        bool operator != (const NVector2& v){
            return (x != v.x) || (y != v.y);
        }
        NVector2 operator + () const{
            return *this;
        }
        NVector2 operator - () const{
            return NVector2(-x, -y);
        }
        NVector2 operator + (const NVector2& v) const{
            return NVector2(x + v.x, y + v.y);
        }
        NVector2 operator - (const NVector2& v) const
        {
            return NVector2(x - v.x, y - v.y);
        }
        NVector2 operator * (const NVector2& v) const{
            return NVector2(x * v.x, y * v.y);
        }
        NVector2 operator * (const T& s) const{
            return NVector2(x * s, y * s);
        }
        NVector2 operator / (const T& s) const{
            assert( s != 0 );
            return NVector2(x / s, y / s);
        }
        NVector2 operator / (const NVector2& v) const{
            return NVector2(x / v.x, y / v.y);
        }
        NVector2& operator += (const NVector2& v){
            x += v.x;
            y += v.y;
            return *this;
        }
        NVector2& operator -= (const NVector2& v){
            x -= v.x;
            y -= v.y;
            return *this;
        }
        NVector2& operator *= (const NVector2& v){
            x *= v.x;
            y *= v.y;
            return *this;
        }
        NVector2& operator *= (const T& s){
            x *= s;
            y *= s;
            return *this;
        }
        NVector2& operator /= (const T& s){
            assert( s != 0 );
            x /= s;
            y /= s;
            return *this;
        }
        NVector2& operator /= (const NVector2& v){
            assert((v.x != 0) && (v.y != 0));
            x /= v.x;
            y /= v.y;
            return *this;
        }
        NVector2& operator = (const NVector2& v){
            x = v.x;
            y = v.y;
            return *this;
        }
        NVector2& operator = (const T& v){
            x = v;
            y = v;
            return *this;
        }

        //swizzles
#ifdef NMATH_SWIZZLE_ENABLE
#include "NVector2Swizzle.h"
#endif
       
    };

    template <typename T>
    inline NVector2<T> operator * (const T& s, const NVector2<T>& v){
        return NVector2<T>(s * v.x, s * v.y);
    }

	typedef NVector2<int32> int2;
    typedef NVector2<float> float2;
    typedef NVector2<double> double2;
}
#endif // NVector2_h__
